/**
 * @file   main.cpp
 * @author ywl <ywl@ywl-VirtualBox>
 * @date   Tue Jan  3 15:18:20 2023
 * 
 * @brief  Programs for Programming Assignments.
 * 
 * 
 */

#include "Spline.h"
#include "Helper.h"

using std::cout;
using std::endl;

int main(int argc, char* argv[])
{
    
    /**
     * Problem A
     */
    cout << "------------------Problem A--------------------" << endl;
    
    int N[5] = {5,10,20,40,80};
    
    // Complete Condition
    cout << "For complete condition:" << endl;
    std::vector<Spline<1,4,ppForm> > Bv1;
    for (int i = 0 ; i < 5 ; i++){
	auto pvB = DataGenerator(Bfunc,-1,1,N[i]);
	Spline<1,4,ppForm> Sp = fitCurve<1,4>(pvB,complete,25.0/338,-25.0/338);
	Bv1.push_back(Sp);
    }
    cout << "Run plot/A_complete.m by matlab to get the plot." << endl;
    // Not a knot
    std::vector<double> err1(5);
    for (int i = 0 ; i < 5 ; i++)
	err1[i] = Berror(Bv1[i],N[i]);
    for (int i = 0 ; i < 4 ; i++){
	cout << "N =  " << N[i]+1 << " :\t error = " << err1[i] << ",\
  \t convergence rate = " << log(err1[i]/err1[i+1])/log(2) << endl;
    }
    cout << "N =  " << N[4]+1 << " : \t error = " << err1[4] << endl;
    cout << "For not-a-knot condition:" << endl;
    std::vector<Spline<1,4,ppForm> > Bv2;
    for (int i = 0 ; i < 5 ; i++){
	auto pvB = DataGenerator(Bfunc,-1,1,N[i]);
	Spline<1,4,ppForm> Sp = fitCurve<1,4>(pvB,notAknot);
	Bv2.push_back(Sp);
    }
    cout << "Run plot/A_notAknot.m by matlab to get the plot." << endl;
    std::vector<double> err2(5);
    for (int i = 0 ; i < 5 ; i++)
	err2[i] = Berror(Bv2[i],N[i]);
    for (int i = 0 ; i < 4 ; i++){
	cout << "N =  " << N[i]+1 << " :\t error = " << err2[i] << ",\
  \t convergence rate = " << log(err2[i]/err2[i+1])/log(2) << endl;
    }
    cout << "N =  " << N[4]+1 << " : \t error = " << err2[4] << endl;
    
    /**
     * Problem C
     */
    cout << "------------------Problem C--------------------" << endl;
    
    cout << "For Theorem 3.57 case:" << endl;
    auto Pc1 = Cgenerator1();
    Spline<1,4,cardinalB> cSp1 = fitCurve<4>(-8,8,Pc1.first,Pc1.second);
    cout << "Run Plot/C_Bspline1.m by matlab to get the plot." << endl;
    
    cout << "For Theorem 3.58 case:" << endl;
    auto Pc2 = Cgenerator2();
    Spline<1,3,cardinalB> cSp2 = fitCurve<3>(-7,7,Pc2.first,Pc2.second);
    cout << "Run Plot/C_Bspline2.m by matlab to get the plot." << endl;
    
    /**
     * Problem D
     * 
     */  
    cout << "------------------Problem D--------------------" << endl;
    
    double site[] = {-3.5,-3,-0.5,0,0.5,3,3.5};
    cout << "\t \t C_Bspline1 \t C_Bspline2" << endl;
    for (int i = 0 ; i < 7 ; i++){
	double tmperr1 = Derror<4>(cSp1,site[i]);
	double tmperr2 = Derror<3>(cSp2,site[i]);
	cout <<"Error at " << site[i] << " :" << "\t " << tmperr1;
	if (i == 3)
	    cout << "\t";
	cout << "\t " << tmperr2 << endl;
    }
    
    /**
     * Problem E
     * 
     */
    cout << "------------------Problem E--------------------" << endl;
    
    int num[] = {10,40,160};
    const Vec<double,2> Dbegin({0,1});
    const Vec<double,2> Dend({0,-1});
    std::vector<std::pair<Spline<2,4,ppForm>,Spline<2,4,ppForm> > > Evpsp;
    for (int i = 0 ; i < 3 ; i++){
	auto info = Egenerator(num[i]);
	Spline<2,4,ppForm> Esp1 =
	    fitCurve<2,4>(info.first,complete,Dbegin,Dend);
	Spline<2,4,ppForm> Esp2 =
	    fitCurve<2,4>(info.second,complete,Dbegin,Dend);
	Evpsp.push_back(std::make_pair(Esp1,Esp2));
    }
    cout << "Run Plot/E_heart.m by matlab to get the plot." << endl;

    /**
     * Problem F
     * 
     */
    cout << "------------------Problem F--------------------" << endl;

    cout << "For n = 1, Run Plot/F_table1.m by matlab to get the plot." << endl;
    cout << "For n = 2, Run Plot/F_table2.m by matlab to get the plot." << endl;   

}
